package com.android.kotlincoroutinemvvmdemo.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.RecyclerView
import com.android.kotlincoroutinemvvmdemo.CoroutineMVVMApp

abstract class BaseRVAdapter<T : ViewDataBinding, M> : RecyclerView.Adapter<BaseRVAdapter.RVViewHolder<T>>() {

    protected lateinit var mBinding: T

    private var mDataSet: MutableList<M>? = null

    protected var mBindingList = mutableListOf<T>()


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RVViewHolder<T> {
        if (enableRecyclerViewPool()) {
            val viewHolder = CommonRecyclerViewPool.getRecycledView(CommonRecyclerViewPool.ITEM_TYPE)
            return if (viewHolder == null) {
                mBinding = DataBindingUtil.inflate(
                    LayoutInflater.from(parent.context),
                    getLayoutId(),
                    parent,
                    false
                )
                mBindingList.add(mBinding)
                val mNewViewHolder = RVViewHolder(mBinding)
                CommonRecyclerViewPool.setMaxRecycledViews(CommonRecyclerViewPool.ITEM_TYPE,5)
                CommonRecyclerViewPool.putRecycledView(mNewViewHolder)
                mNewViewHolder
            } else {
                val mRVViewHolder = viewHolder as? RVViewHolder<T>
                mBinding = mRVViewHolder!!.mBinding
                mBindingList.add(mRVViewHolder.mBinding)
                mRVViewHolder
            }
        } else {
            mBinding = DataBindingUtil.inflate(
                LayoutInflater.from(parent.context),
                getLayoutId(),
                parent,
                false
            )
            mBindingList.add(mBinding)
            return RVViewHolder(mBinding)
        }
    }

    override fun onBindViewHolder(holder: RVViewHolder<T>, position: Int) {
        mDataSet?.apply {
            bindData(holder, get(position), holder.layoutPosition)
        }
        holder.mBinding.executePendingBindings()

        adapterUIModeNightForRecyclerView(
            holder.mBinding,
            CoroutineMVVMApp.instance!!.isDarkTheme()
        )
    }

    override fun onBindViewHolder(holder: RVViewHolder<T>, position: Int, payloads: MutableList<Any>) {
        super.onBindViewHolder(holder, position, payloads)
        if (payloads.isEmpty()) {
            onBindViewHolder(holder, position)
        } else {
            //通过payloads参数实现局部刷新
            //局部刷新有两种方式:1.修改item内容 payloads参数并调用notifyItemChanged(position : Int,payloads : Any)实现
            //2.动态添加或删除item 需使用notifyItemInserted(int)、notifyItemMoved(int)、notifyItemRemoved(int)。插入、移动一个并自动刷新。
            localRefreshItemContent(holder, position, payloads, mDataSet!![position])
        }
    }

    override fun getItemCount(): Int = mDataSet?.size ?: 0

    abstract fun getLayoutId(): Int

    abstract fun bindData(holder: RVViewHolder<T>, dataItem: M, position: Int)

    open fun localRefreshItemContent(holder: RVViewHolder<T>, position: Int, payloads: MutableList<Any>, dataItem: M? = null) {}

    open fun adapterUIModeNightForRecyclerView(uiModeNight: Boolean) {}

    open fun adapterUIModeNightForRecyclerView(mBinding: T, uiModeNight: Boolean) {}

    open fun enableRecyclerViewPool() = false

    fun setDataSet(mDataSet: MutableList<M>? = null) {
        mDataSet?.let {
            this.mDataSet = mDataSet
            notifyItemRangeChanged(0, this.mDataSet!!.size)
        }
    }

    fun removeDataItem(dataItem: M, position: Int) {
        mDataSet?.let {
            it.remove(dataItem)
            notifyItemRemoved(position)
        }
    }

    fun addDataItem(dataItem: M) {
        mDataSet?.let {
            val originalSize = it.size
            it.add(originalSize,dataItem)
            notifyItemRangeInserted(it.size, 1)
        }
    }

    fun addDataItem(dataItem: M, position: Int) {
        mDataSet?.let {
            val originalSize = it.size
            if (position in 0..< originalSize) {
                it.add(position, dataItem)
                notifyItemRangeInserted(position, 1)
            } else if (position < 0) {
                it.add(0, dataItem)
                notifyItemRangeInserted(0, 1)
            } else {
                it.add(originalSize,dataItem)
                notifyItemRangeInserted(it.size, 1)
            }
        }
    }

    class RVViewHolder<T : ViewDataBinding>(viewBinding: T) : RecyclerView.ViewHolder(viewBinding.root) {
        val mBinding = viewBinding
    }
}